﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using NLog;

namespace Tab2Sql
{
    #region DateFormsEnum
    /// <summary>
    ///
    /// </summary>
    public enum DateForms
    {
        /// <summary>
        /// UK / European dates like 31/03/2000
        /// </summary>
        DDMMYYYY_SLASHES,
        /// <summary>
        ///
        /// </summary>
        DDMMYYYY_PERIODS,
        /// <summary>
        ///
        /// </summary>
        DDMMYYYY_HYPHENS,
        /// <summary>
        ///
        /// </summary>
        DDMMYYYY_NONE,
        /// <summary>
        /// US Dates like 03/31/2000
        /// </summary>
        MMDDYYYY_SLASHES,
        /// <summary>
        ///
        /// </summary>
        MMDDYYYY_PERIODS,
        /// <summary>
        ///
        /// </summary>
        MMDDYYYY_HYPHENS,
        /// <summary>
        ///
        /// </summary>
        MMDDYYYY_NONE,
        /// <summary>
        /// ISO Dates (2000-03-31)
        /// </summary>
        YYYYMMDD_SLASHES,
        /// <summary>
        ///
        /// </summary>
        YYYYMMDD_HYPHENS,
        /// <summary>
        ///
        /// </summary>
        YYYYMMDD_PERIODS,
        /// <summary>
        ///
        /// </summary>
        YYYYMMDD_NONE,
        /// <summary>
        /// 2 Year UK Dates
        /// </summary>
        DDMMYY_SLASHES,
        /// <summary>
        ///
        /// </summary>
        DDMMYY_PERIODS,
        /// <summary>
        ///
        /// </summary>
        DDMMYY_HYPHENS,
        /// <summary>
        /// 2 Year US Dates
        /// </summary>
        MMDDYY_SLASHES,
        /// <summary>
        ///
        /// </summary>
        MMDDYY_PERIODS,
        /// <summary>
        ///
        /// </summary>
        MMDDYY_HYPHENS,


        /// <summary>
        /// 01 Jan 2000
        /// </summary>
        DDmmmmYYYY_SPACES,
        /// <summary>
        /// Jan 01 2000
        /// </summary>
        mmmmDDYYYY_SPACES,
        /// <summary>
        /// 
        /// </summary>
        UNIX_EPOCH_TIME
    }
    #endregion
    /// <summary>
    ///
    /// </summary>
    public partial class InputAdjustment
    {


        private static Logger logger = LogManager.GetCurrentClassLogger ();
        /// <summary>
        ///
        /// </summary>
        /// <param name="myTag">
        /// A <see cref="System.String"/>
        /// </param>
        /// <param name="inputString">
        /// A <see cref="System.String"/>
        /// </param>
        /// <returns>
        /// A <see cref="System.String"/>
        /// </returns>
        public static string GetRidOf (string myTag, string inputString)
        {

            string searchText = "";
            string replacementText = "";

            if (myTag == "getRid-custom")
            {

                string temporaryDivide = Guid.NewGuid ().ToString ();
                string[] temporaryDelimiter = new string[1];
                temporaryDelimiter[0] = temporaryDivide;

                var resultSet = removeCustom (temporaryDivide).Split (temporaryDelimiter, StringSplitOptions.None);

                if (resultSet.Length > 0)
                {
                    searchText = resultSet[0];
                    replacementText = resultSet[1];
                }

                
                
                
                
                
            } else
            {
                searchText = getRemovalPattern (myTag);
            }
            return getRidOf (searchText, replacementText, inputString, true);
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="regexPattern">
        /// A <see cref="System.String"/>
        /// </param>
        /// <param name="inputString">
        /// A <see cref="System.String"/>
        /// </param>
        /// <param name="alt">
        /// A <see cref="System.Boolean"/>
        /// </param>
        /// <returns>
        /// A <see cref="System.String"/>
        /// </returns>
        public static string GetRidOf (string regexPattern, string inputString, bool alt)
        {
            string pattern = regexPattern;
            return getRidOf (pattern, string.Empty, inputString, true);

        }




        private static string getRidOf (string pattern, string replacementText, string target, bool useRegularExpression)
        {
            string endString = String.Empty;
            try
            {
                System.Text.RegularExpressions.Regex regex = new Regex (pattern);
                endString = regex.Replace (target, replacementText);
                regex = null;
                return endString;
            } catch (Exception ex)
            {
                logger.Error ("getRidOf Error - possibly invalid Regex pattern provided. Exception message : {0}.", ex.Message);
                return target;
            }
            
        }
        private static string getRemovalPattern (string myTag)
        {
            string getRidOfPattern = String.Empty;
            switch (myTag)
            {
            case "getRid-sq":
                getRidOfPattern = "'";
                break;
            case "getRid-dq":
                getRidOfPattern = "\"";
                break;
            case "getRid-currency":
                getRidOfPattern = "£|$";
                break;
            case "getRid-excess":
                getRidOfPattern = "[ ]{3,}";
                break;
            case "getRid-trim":
                getRidOfPattern = @"\s+$";
                break;
            case "getRid-timestamp":
                getRidOfPattern = @"[0-2][0-9]:[0-6][0-9]:[0-6][0-9](\.[0-9][0-9][0-9])?";
                break;

            default:
                break;
            }
            
            return getRidOfPattern;
            
            
            
        }
        private static string removeCustom (string temporaryDividor)
        {
            
            string moo = "";
            Tab2Sql.Forms.CustomReplace cr = new Tab2Sql.Forms.CustomReplace (ref moo);
            cr.Activate ();
            cr.ShowDialog ();
            
            
            string searchPattern = cr.SearchPattern;
            string replacePattern = cr.ReplacePattern;
            string foo = string.Format ("{0}{1}{2}", searchPattern, temporaryDividor, replacePattern);
            
            
            cr.RemoteClose ();
            return foo;
            
            
            
            
        }
        private static string removeCustom ()
        {
            
            string moo = "";
            Tab2Sql.Forms.CustomReplace cr = new Tab2Sql.Forms.CustomReplace (ref moo);
            cr.Activate ();
            cr.ShowDialog ();
            
            string foo = cr.SearchPattern;
            
            cr.RemoteClose ();
            return foo;
            
            
            
            
        }

        /// <summary>
        ///
        /// </summary>
        /// <param name="inputText">
        /// A <see cref="System.String"/>
        /// </param>
        /// <param name="From">
        /// A <see cref="DateForms"/>
        /// </param>
        /// <param name="To">
        /// A <see cref="DateForms"/>
        /// </param>
        /// <returns>
        /// A <see cref="System.String"/>
        /// </returns>
        public static string DateConvert (string inputText, DateForms From, DateForms To)
        {
            //Regex r;
            
            string fromPattern = @"([0-3][0-9])\.([0-1][0-9])\.([0-2][0-9][0-9][0-9])";
            string toPattern = @"01/01/2000";
            bool dmy = true;
            bool ymd = false;
            
            
            switch (From)
            {
            case DateForms.DDMMYYYY_SLASHES:
                fromPattern = @"([0-3][0-9])\/([0-1][0-9])\/([0-2][0-9][0-9][0-9])";
                break;
            case DateForms.DDMMYYYY_PERIODS:
                fromPattern = @"([0-3][0-9])\.([0-1][0-9])\.([0-2][0-9][0-9][0-9])";
                break;
            case DateForms.DDMMYYYY_HYPHENS:
                fromPattern = @"([0-3][0-9])\-([0-1][0-9])\-(200[2-9])";
                break;
            case DateForms.DDMMYYYY_NONE:
                fromPattern = @"([0-3][0-9])([0-1][0-9])(200[2-9])";
                break;
            case DateForms.DDMMYY_SLASHES:
                fromPattern = @"([0-3][0-9])\/([0-1][0-9])\/([0-9][0-9])";
                break;
            case DateForms.DDMMYY_PERIODS:
                fromPattern = @"([0-3][0-9])\.([0-1][0-9])\.([0-9][0-9])";
                break;
            case DateForms.DDMMYY_HYPHENS:
                fromPattern = @"([0-3][0-9])\-([0-1][0-9])\-([0-9][0-9])";
                break;
            case DateForms.MMDDYYYY_SLASHES:
                fromPattern = @"([0-1][0-9])\/([0-3][0-9])\/([0-2][0-9][0-9][0-9])";
                dmy = false;
                break;
            case DateForms.MMDDYYYY_PERIODS:
                fromPattern = @"([0-1][0-9])\.([0-3][0-9])\.([0-2][0-9][0-9][0-9])";
                dmy = false;
                break;
            case DateForms.MMDDYYYY_HYPHENS:
                fromPattern = @"([0-1][0-9])\-([0-3][0-9])\-([0-2][0-9][0-9][0-9])";
                dmy = false;
                break;
            
            case DateForms.MMDDYYYY_NONE:
                fromPattern = @"([0-1][0-9])([0-3][0-9])([0-2][0-9][0-9][0-9])";
                dmy = false;
                break;
            case DateForms.MMDDYY_SLASHES:
                dmy = false;
                break;
            case DateForms.MMDDYY_PERIODS:
                dmy = false;
                break;
            case DateForms.MMDDYY_HYPHENS:
                dmy = false;
                break;
            case DateForms.UNIX_EPOCH_TIME:
                dmy = false;
                break;
            case DateForms.YYYYMMDD_HYPHENS:
                dmy = false;
                ymd = true;
                fromPattern = @"([0-2][0-9][0-9][0-9])\-([0-1][0-9])\-([0-3][0-9])(\s[0-2][0-9]:[0-6][0-9]:[0-9][0-9]\.[0-9][0-9][0-9])?";
                break;
            case DateForms.YYYYMMDD_PERIODS:
                dmy = false;
                ymd = true;
                fromPattern = @"([0-2][0-9][0-9][0-9])\.([0-1][0-9])\.([0-3][0-9])(\s[0-2][0-9]:[0-6][0-9]:[0-9][0-9]\.[0-9][0-9][0-9])?";
                break;
            case DateForms.YYYYMMDD_SLASHES:
                dmy = false;
                ymd = true;
                fromPattern = @"([0-2][0-9][0-9][0-9])\/([0-1][0-9])\/([0-3][0-9])(\s[0-2][0-9]:[0-6][0-9]:[0-9][0-9]\.[0-9][0-9][0-9])?";
                break;
            case DateForms.DDmmmmYYYY_SPACES:
                dmy = true;
                fromPattern = @"([0-9][0-9] (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) ([0-2][0-9][0-9][0-9])";
                break;
            case DateForms.mmmmDDYYYY_SPACES:
                dmy = true;
                fromPattern = @"(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) ([0-9][0-9] ([0-2][0-9][0-9][0-9])";
                break;
            default:
                break;
            }
            switch (To)
            {
            case DateForms.DDMMYYYY_SLASHES:
                if (dmy == true)
                {
                    toPattern = @"$1/$2/$3";
                } else if (ymd == true)
                {
                    toPattern = @"$3/$2/$1";
                } else
                {
                    toPattern = @"$2/$1/$3";
                }
                
                break;
            case DateForms.DDMMYYYY_PERIODS:
                if (dmy == true)
                {
                    toPattern = @"$1.$2.$3";
                } else
                {
                    toPattern = @"$2.$1.$3";
                }
                break;
            case DateForms.DDMMYYYY_HYPHENS:
                if (dmy == true)
                {
                    toPattern = @"$1-$2-$3";
                } else
                {
                    toPattern = @"$2-$1-$3";
                }
                
                break;
            case DateForms.DDMMYY_SLASHES:
                break;
            case DateForms.DDMMYY_PERIODS:
                break;
            case DateForms.DDMMYY_HYPHENS:
                break;
            case DateForms.MMDDYYYY_SLASHES:
                toPattern = @"$2/$1/$3";
                break;
            case DateForms.MMDDYYYY_PERIODS:
                toPattern = @"$2.$1.$3";
                break;
            case DateForms.MMDDYYYY_HYPHENS:
                toPattern = @"$2-$1-$3";
                break;
            case DateForms.MMDDYY_SLASHES:
                break;
            case DateForms.MMDDYY_PERIODS:
                break;
            case DateForms.MMDDYY_HYPHENS:
                break;
            case DateForms.UNIX_EPOCH_TIME:
                return specialMatches (inputText, fromPattern);
            case DateForms.YYYYMMDD_HYPHENS:
                if (dmy == true)
                {
                    toPattern = @"$3-$2-$1";
                } else if (ymd == true)
                {
                    toPattern = @"$1-$2-$3";
                } else
                {
                    toPattern = @"$3-$1-$2";
                }
                break;
            default:
                break;
            }
            
            
            return Regex.Replace (inputText, fromPattern, toPattern);
        }


        private static long ToUnixEpoch (string dateTime)
        {
            DateTime dt = new DateTime ();
            if (DateTime.TryParse (dateTime, out dt))
            {
                return ToUnixEpoch (dt);
            } else
            {
                return -1;
            }
            
        }
        private static long ToUnixEpoch (DateTime dt)
        {
            return (dt.ToUniversalTime ().Ticks - 621355968000000000) / 10000000;
        }

        private static string specialMatches (string inputText, string fromPattern)
        {
            string modified = inputText;
            //  System.Windows.Forms.MessageBox.Show(fromPattern + inputText.Length.ToString()+ " chars");
            Regex r = new Regex (fromPattern);
            //  System.Windows.Forms.MessageBox.Show(r.IsMatch(inputText).ToString());
            foreach (Match m in r.Matches (inputText))
            {
                string replaceText = m.ToString ();
                string replaceWith = ToUnixEpoch (replaceText).ToString ();
                // System.Windows.Forms.MessageBox.Show(replaceText+replaceWith);
                modified = modified.Replace (replaceText, replaceWith);
            }
            
            return modified;
        }

        /// <summary>
        /// Adjusts the capitalisation of input box
        /// </summary>
        /// <param name="inputArray">
        /// A <see cref="System.String[]"/>
        /// </param>
        /// <param name="caseChangeRequested">
        /// A <see cref="CaseChangeRequested"/>
        /// </param>
        public static void AdjustCase (ref string[] inputArray, CaseChangeRequested caseChangeRequested)
        {
            for (int i = 0; i < inputArray.Length; i++)
            {
                switch (caseChangeRequested)

                {
                case CaseChangeRequested.tolower:
                    inputArray[i] = inputArray[i].ToLower ();
                    break;
                case CaseChangeRequested.toupper:
                    inputArray[i] = inputArray[i].ToUpper ();
                    break;
                case CaseChangeRequested.none:
                    logger.Info ("InputAdjustment.AdjustCase has been called but no change required - doing nothing.");
                    return;
                    break;

                default:
                    logger.Info ("InputAdjustment.AdjustCase has been called but invalid/missing CaseChangeRequested value - doing nothing.");
                    return;
                    break;
                }

            }
        }


        public static void SortInputText (ref string[] inputArray)
        {
            var sort = from s in inputArray
                orderby s
                select s;
            
            
            inputArray = sort.ToArray ();
            
        }
        
        
    }
}
